package com.github.prontera.common.auth0.jwt.algorithms;

import com.github.prontera.common.auth0.jwt.exceptions.SignatureGenerationException;
import com.github.prontera.common.auth0.jwt.exceptions.SignatureVerificationException;

import java.io.UnsupportedEncodingException;
import java.security.interfaces.ECKey;
import java.security.interfaces.RSAKey;

/**
 * 创建token相关算法
 */
public abstract class Algorithm {

	private final String name;
	private final String description;

	/**
	 * RS256 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm RSA256(RSAKey key) throws IllegalArgumentException {
		return new RSAAlgorithm("RS256", "SHA256withRSA", key);
	}

	/**
	 * RS384 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm RSA384(RSAKey key) throws IllegalArgumentException {
		return new RSAAlgorithm("RS384", "SHA384withRSA", key);
	}

	/**
	 * RS512 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm RSA512(RSAKey key) throws IllegalArgumentException {
		return new RSAAlgorithm("RS512", "SHA512withRSA", key);
	}

	/**
	 * HS256 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm HMAC256(String secret) throws IllegalArgumentException, UnsupportedEncodingException {
		return new HMACAlgorithm("HS256", "HmacSHA256", secret);
	}

	/**
	 * HS384 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm HMAC384(String secret) throws IllegalArgumentException, UnsupportedEncodingException {
		return new HMACAlgorithm("HS384", "HmacSHA384", secret);
	}

	/**
	 * HS512 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm HMAC512(String secret) throws IllegalArgumentException, UnsupportedEncodingException {
		return new HMACAlgorithm("HS512", "HmacSHA512", secret);
	}

	/**
	 * HS256 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm HMAC256(byte[] secret) throws IllegalArgumentException {
		return new HMACAlgorithm("HS256", "HmacSHA256", secret);
	}

	/**
	 * HS384 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm HMAC384(byte[] secret) throws IllegalArgumentException {
		return new HMACAlgorithm("HS384", "HmacSHA384", secret);
	}

	/**
	 * HS512 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm HMAC512(byte[] secret) throws IllegalArgumentException {
		return new HMACAlgorithm("HS512", "HmacSHA512", secret);
	}

	/**
	 * ES256 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm ECDSA256(ECKey key) throws IllegalArgumentException {
		return new ECDSAAlgorithm("ES256", "SHA256withECDSA", 32, key);
	}

	/**
	 * ES384 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm ECDSA384(ECKey key) throws IllegalArgumentException {
		return new ECDSAAlgorithm("ES384", "SHA384withECDSA", 48, key);
	}

	/**
	 * ES512 算法
	 * 
	 * @param key
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static Algorithm ECDSA512(ECKey key) throws IllegalArgumentException {
		return new ECDSAAlgorithm("ES512", "SHA512withECDSA", 66, key);
	}

	public static Algorithm none() {
		return new NoneAlgorithm();
	}

	protected Algorithm(String name, String description) {
		this.name = name;
		this.description = description;
	}

	public String getName() {
		return name;
	}

	String getDescription() {
		return description;
	}

	@Override
	public String toString() {
		return description;
	}

	/**
	 * 验证token
	 */
	public abstract void verify(byte[] contentBytes, byte[] signatureBytes) throws SignatureVerificationException;

	/**
	 * 签名
	 */
	public abstract byte[] sign(byte[] contentBytes) throws SignatureGenerationException;
}
